package com.ews.onlineexchange.service;

import java.io.Serializable;
import java.util.List;

import javax.enterprise.context.SessionScoped;
import javax.faces.context.FacesContext;
import javax.inject.Inject;
import javax.inject.Named;
import javax.persistence.EntityManager;
import javax.persistence.Query;
import javax.transaction.Transactional;

import com.ews.onlineexchange.model.User;
import com.ews.onlineexchange.shiro.Digests;
import com.ews.onlineexchange.util.Encodes;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.subject.Subject;

@Named
@SessionScoped
public class UserService implements Serializable {

	/**
	 *
	 */
	private static final long serialVersionUID = 1L;
	public static final String HASH_ALGORITHM = "SHA-1";
	public static final int HASH_INTERATIONS = 1024;
	public static final int SALT_SIZE = 8;
	@Inject
	EntityManager entityManager;

//	@Inject
//	KeycloakUserService keycloakUserService;

	private User loginedUser;

	private static final String QUERY_USER_BY_USERNAME_EQL = ""
			+ "	SELECT			user"
			+ "	FROM			User user"
			+ "	WHERE			LOWER(user.username) = LOWER(:username)	";

	/**
	 * 这里加delFlag = 0 ，是为了禁止删除的用户登录
	 * @param username
	 * @return
	 */
	public User findByUsername(String username) {
		Query query = entityManager.createQuery(QUERY_USER_BY_USERNAME_EQL);
		query.setParameter("username", username);
		List<User> resultList = query.getResultList();
		if (resultList.size() > 0) {

			return resultList.get(0);
		}
		return null;
	}
	private static final String QUERY_USER_BY_SDZWUSERNAME_EQL = "				"
			+ "	SELECT			user											"
			+ "	FROM			User user										"
			+ "	WHERE			LOWER(user.sdzwUsername) = LOWER(:sdzwUsername)	"
			+ "	AND 			user.delFlag = '0' 								";
	public User findBySdzwUsername(String sdzwUsername) {
		Query query = entityManager.createQuery(QUERY_USER_BY_SDZWUSERNAME_EQL);
		query.setParameter("sdzwUsername", sdzwUsername);
		List<User> resultList = query.getResultList();
		if (resultList.size() > 0) {

			return resultList.get(0);
		}
		return null;
	}

	private static final String EXIST_USER_PUSHKEY_EQL = ""
			+ "	SELECT			count(user)"
			+ "	FROM			User user"
			+ "	WHERE			user.id = :userId	"
			+ "	AND 			user.pushKey is not null ";
	public boolean existPushKey(String userId) {
		Query query = entityManager.createQuery(EXIST_USER_PUSHKEY_EQL);
		query.setParameter("userId", userId);
		long count = (long)query.getSingleResult();
		if (count > 0) return true;
		else return false;
	}

	private static final String EXIST_USER_USERNAME_EQL = ""
			+ "	SELECT			count(user)"
			+ "	FROM			User user"
			+ "	WHERE			user.username = :username	";

	/**
	 * 不理不允许加 delFlag，因为username 是 unique
	 * @param username
	 * @return
	 */
	public boolean existUsername(String username) {
		Query query = entityManager.createQuery(EXIST_USER_USERNAME_EQL);
		query.setParameter("username", username);
		long count = (long)query.getSingleResult();
		if (count > 0) return true;
		else return false;
	}

	private static final String EXIST_USER_SDZWUSERNAME_EQL = ""
			+ "	SELECT			count(user)"
			+ "	FROM			User user"
			+ "	WHERE			user.sdzwUsername = :sdzwUsername	"
			+ " AND 			user.delFlag = '0' ";
	public boolean existSdzwUsername(String sdzwUsername) {
		Query query = entityManager.createQuery(EXIST_USER_SDZWUSERNAME_EQL);
		query.setParameter("sdzwUsername", sdzwUsername);
		long count = (long)query.getSingleResult();
		if (count > 0) return true;
		else return false;
	}

	public void updatePushKey(String userId,String pushKey) {
		User user = entityManager.find(User.class, userId);
//		user.setPushKey(pushKey);
		entityManager.merge(user);
	}

	public User findLoginedUser() {
//		String loginedUsername = (String)SecurityUtils.getSubject().getPrincipal();
		User user = (User) SecurityUtils.getSubject().getPrincipal();
		return user;
	}

	public User getLoginedUser() {
		if (loginedUser == null)
			initLoginedUser();
		return loginedUser;
	}
	public boolean hasRole(String role){
		Subject subject = SecurityUtils.getSubject();
		return subject.hasRole(role);
	}
	public void setLoginedUser(User loginedUser) {
		this.loginedUser = loginedUser;
	}

	private void initLoginedUser() {
		this.loginedUser = findLoginedUser();
	}

	private static final String QUERY_USER_BY_CNNAME_EQL = ""
			+ "	SELECT			count(user)"
			+ "	FROM			User user"
			+ "	WHERE			user.cnname = :cnname "
			+ " AND 			user.delFlag = '0' ";
	public boolean isCnnameExist(String cnname) {
		Query query = entityManager.createQuery(QUERY_USER_BY_CNNAME_EQL);
		query.setParameter("cnname", cnname);
		long count = (long)query.getSingleResult();
		if (count > 0) {
			return true;
		}else return false;
	}

	private static final String QUERY_USER_BY_EMAIL_EQL = ""
			+ "	SELECT			count(user)"
			+ "	FROM			User user"
			+ "	WHERE			user.email = :email ";
	public boolean isEmailExist(String email) {
		Query query = entityManager.createQuery(QUERY_USER_BY_EMAIL_EQL);
		query.setParameter("email", email);
		long count = (long)query.getSingleResult();
		if (count > 0) {
			return true;
		}else return false;
	}

	/**
	 * 生成安全的密码，生成随机的16位salt并经过1024次 sha-1 hash
	 */
	public String entryptPassword(String plainPassword) {
		byte[] salt = Digests.generateSalt(SALT_SIZE);
		byte[] hashPassword = Digests.sha1(plainPassword.getBytes(), salt, HASH_INTERATIONS);
		return Encodes.encodeHex(salt) + Encodes.encodeHex(hashPassword);
	}

	/**
	 * 验证密码
	 *
	 * @param plainPassword
	 *            明文密码
	 * @param password
	 *            密文密码
	 * @return 验证成功返回true
	 */
	public boolean validatePassword(String plainPassword, String password) {
		byte[] salt = Encodes.decodeHex(password.substring(0, 16));
		byte[] hashPassword = Digests.sha1(plainPassword.getBytes(), salt, HASH_INTERATIONS);
		return password.equals(Encodes.encodeHex(salt) + Encodes.encodeHex(hashPassword));
	}

	@Transactional
	public void merge(User user){
		entityManager.merge(user);
	}
}
